package cn.elegent.tx.core.sys;

import cn.elegent.ac.ACHandler;
import cn.elegent.ac.annotation.Topic;
import cn.elegent.tx.context.Snapshot;
import cn.elegent.tx.core.entity.TransactionEntity;
import cn.elegent.tx.core.entity.state.TransactionState;
import cn.elegent.tx.core.manager.TransactionManagerImpl;
import cn.elegent.tx.core.rollback.RollBackDTO;
import cn.elegent.tx.core.rollback.RollBackHandler;
import cn.elegent.tx.core.storage.TransactionStorage;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * RollBackHandler
 * @description 默认提供的回滚消息分发处理类
 * @author WGL
 * @date 2022/11/7 17:14
*/
@Topic(value = TransactionManagerImpl.ROLLBACK_TOPIC+"${spring.application.name}")
@Component
@Slf4j
public class RollBackHandlerTemplate implements ACHandler<RollBackDTO> {

    @Autowired
    private TransactionStorage storage;

    @Override
    public void process(String topic,RollBackDTO dto){
        log.info("Elegent-ACTX 处理回滚消息：{} {}",topic,dto);
        TransactionEntity transactionEntity = new TransactionEntity();
        BeanUtils.copyProperties(dto,transactionEntity);
        storage.change(transactionEntity, TransactionState.BEGIN_ROLL_BACK);
        String childName = dto.getChildName();
        String mainName = dto.getMainName();
        RollBackHandler rollBackHandler = (RollBackHandler)RollBackData.get(mainName + "/" + childName);
        try {
            //找到对应的实现类开始执行回滚逻辑
            Map byJson = JSON.parseObject( dto.getArgs(), Map.class );
            Snapshot snapshot=new Snapshot(byJson);

            rollBackHandler.doRollBack(topic,snapshot);
            //回滚成功---修改状态为回滚成功
            storage.change(transactionEntity, TransactionState.END_ROLL_BACK);
            log.info("Elegent-ACTX 处理回滚消息成功：{}",transactionEntity);
        }catch (Exception e){
            e.printStackTrace();
            //如果回滚逻辑出错--修改状态为回滚失败
            storage.change(transactionEntity, TransactionState.ERROR_ROLL_BACK);
            log.info("Elegent-ACTX 处理回滚消息失败：{}",transactionEntity);
        }
    }
}
